package com.briup.pai.listener;


import com.alibaba.fastjson2.JSON;
import com.briup.pai.common.constant.ModelConstant;
import com.briup.pai.common.enums.TrainingStatusEnum;
import com.briup.pai.convert.EvaluateErrorConvert;
import com.briup.pai.convert.EvaluateLabelConvert;
import com.briup.pai.entity.message.ModelEvaluateResultMessage;
import com.briup.pai.entity.po.Evaluate;
import com.briup.pai.entity.po.EvaluateError;
import com.briup.pai.entity.po.EvaluateLabel;
import com.briup.pai.entity.po.Model;
import com.briup.pai.service.IEvaluateErrorService;
import com.briup.pai.service.IEvaluateLabelService;
import com.briup.pai.service.IEvaluateService;
import com.briup.pai.service.IModelService;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Component
@CacheConfig(cacheNames = ModelConstant.MODEL_CACHE_PREFIX)
public class ModelEvaluateRabbitListener {

    @Autowired
    private IEvaluateService evaluateService;
    @Autowired
    private IEvaluateLabelService evaluateLabelService;
    @Autowired
    private IEvaluateErrorService evaluateErrorService;
    @Autowired
    private IModelService modelService;

    @Autowired
    private EvaluateLabelConvert evaluateLabelConvert;
    @Autowired
    private EvaluateErrorConvert evaluateErrorConvert;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "${mq.evaluate.result-queue}",durable = "true"),
            exchange = @Exchange(value = "${mq.evaluate.exchange}"),
            key = "${mq.evaluate.result-routing-key}"
    ))
    @Transactional
    public void receiveEvaluateMessage(String message){
        ModelEvaluateResultMessage resultMessage = JSON.parseObject(message, ModelEvaluateResultMessage.class);
        ((ModelEvaluateRabbitListener) AopContext.currentProxy()).processEvaluateResult(resultMessage);
    }

    @Transactional
    @CacheEvict(key = "T(com.briup.pai.common.constant.CommonConstant).DETAIL_CACHE_PREFIX+':'+#modelId")
    public void processEvaluateResult(ModelEvaluateResultMessage resultMessage) {
        // 获取信息，修改评估的准确率
        Integer evaluateId = resultMessage.getEvaluateId();
        Evaluate evaluate = evaluateService.getById(evaluateId);
        evaluate.setAccuracyRate(resultMessage.getAccuracyRate());
        evaluateService.updateById(evaluate);

        // 保存评估结果，将结果转换为EvaluateLabel对象
        List<EvaluateLabel> evaluateLabelList = resultMessage.getLabelResults().stream().map(s -> {
            EvaluateLabel evaluateLabel = evaluateLabelConvert.labelResultMessage2Po(s);
            evaluateLabel.setEvaluateId(evaluateId);
            return evaluateLabel;
        }).toList();
        evaluateLabelService.saveBatch(evaluateLabelList);

        // 保存评估错误。将错误转换为EvaluateError对象
        List<EvaluateError> evaluateErrorList = resultMessage.getEvaluateErrors().stream().map(s -> {
            EvaluateError evaluateError = evaluateErrorConvert.evaluateErrorMessage2Po(s);
            evaluateError.setEvaluateId(evaluateId);
            return evaluateError;
        }).toList();
        evaluateErrorService.saveBatch(evaluateErrorList);

        // 更新模型的训练状态为已完成
        Model model = modelService.getById(resultMessage.getModelId());
        model.setTrainingStatus(TrainingStatusEnum.DONE.getStatus());
        modelService.updateById(model);
    }
}
